import {
    CRC16,
    stringToAsciiBytes,
    hexStr2Bytes,
    bytesToInt,
    MsgType,
    DeviceMessageSend,
    DeviceMessageReceive,
    CommonConfirmReplyMsgBody,
    RecipeSendMsgBody,
    RecipeStepInfo,
    RecipeStartCookingMsgBody,
    ElectronicScaleFoodPreparationMsgBody,
    FoodWeightInfo,
    RangeHoodFanControlMsgBody,
    SettingSeasoningRatioCalibrationMsgBody,
    SeasoningRatioCalibrationInfo,
    ManualAddSeasoningMsgBody,
    SeasoningAddInfo,
    SettingSeasoningBaseUnitMsgBody,
    DeviceEmergencyOperationMsgBody,
} from '@/utils/deviceProtocolUtil.js'

import {
    DeviceModel, 
    DeviceStatus,
} from '@/interface/device.js'

import { deviceProtocolListenerService } from './deviceProtocolListenerService'
import { DeviceProtocolBase } from './DeviceProtocolBase'

/**
 * 设备手动操作协议服务
 */
class DeviceProtocolManualService extends DeviceProtocolBase {
    constructor() {
        super()
    }

    /**
     * 开始手动洗锅
     * @param {String} deviceSn 设备SN号
     */
    startManualWashPot(deviceSn) {
        g_utils.writeLog("准备发送【开始手动洗锅】命令给设备：", deviceSn)
    
        // 封装成发送消息
        let deviceMessageSendEntity = new DeviceMessageSend(deviceSn, MsgType.ManualStartWashPot, null)
        let deviceReplyMsgPredicate = (msg) => {
            // msg 是一个 DeviceMessageReceive 数据类型
            g_utils.writeLog("【开始手动洗锅】命令断言函数参数：", msg)
            // 设备接收后，回复结果 CommonConfirmReplyMsgBody
            let b = msg.msgBody.result > 0
            let status = msg.msgBody.status // 正确则回复手动洗锅的状态
            if (b) {
                g_utils.writeLog("发送【开始手动洗锅】命令成功")
            } else {
                g_utils.writeLog("发送【开始手动洗锅】命令失败")
            }
            
            // TODO: 记录设备烹饪的状态信息
            g_utils.writeLog("准备更新设备状态信息：", msg.msgBody)
            return b
        }
        return this.deviceProtocolStore.sendMessageWithReplyPredicate(deviceMessageSendEntity, deviceReplyMsgPredicate)
    }
    /**
     * 完成手动洗锅
     * @param {String} deviceSn 设备SN号
     */
    finishManualWashPot(deviceSn) {
        g_utils.writeLog("准备发送【完成手动洗锅】命令给设备：", deviceSn)
    
        // 封装成发送消息
        let deviceMessageSendEntity = new DeviceMessageSend(deviceSn, MsgType.ManualFinishWashPot, null)
        let deviceReplyMsgPredicate = (msg) => {
            // msg 是一个 DeviceMessageReceive 数据类型
            g_utils.writeLog("【完成手动洗锅】命令断言函数参数：", msg)
            // 设备接收后，回复结果 CommonConfirmReplyMsgBody
            let b = msg.msgBody.result > 0
            let status = msg.msgBody.status // 正确则回复：正在复位
            if (b) {
                g_utils.writeLog("发送【完成手动洗锅】命令成功")
            } else {
                g_utils.writeLog("发送【完成手动洗锅】命令失败")
            }
            
            // TODO: 记录设备烹饪的状态信息
            g_utils.writeLog("准备更新设备状态信息：", msg.msgBody)
            return b
        }
        return this.deviceProtocolStore.sendMessageWithReplyPredicate(deviceMessageSendEntity, deviceReplyMsgPredicate)
    }
    
    /**
     * 关机
     * @param {String} deviceSn 设备SN号
     */
    shutdownDevice(deviceSn) {
        g_utils.writeLog("准备发送【关机】命令给设备：", deviceSn)
    
        // 封装成发送消息
        let deviceMessageSendEntity = new DeviceMessageSend(deviceSn, MsgType.ManualShutdown, null)
        let deviceReplyMsgPredicate = (msg) => {
            // msg 是一个 DeviceMessageReceive 数据类型
            g_utils.writeLog("【关机】命令断言函数参数：", msg)
            // 设备接收后，回复结果 CommonConfirmReplyMsgBody
            let b = msg.msgBody.result > 0
            let status = msg.msgBody.status // 正确则回复状态：正在关机
            if (b) {
                g_utils.writeLog("发送【关机】命令成功")
            } else {
                g_utils.writeLog("发送【关机】命令失败")
            }
            
            // TODO: 记录设备烹饪的状态信息
            g_utils.writeLog("准备更新设备状态信息：", msg.msgBody)
            return b
        }
        return this.deviceProtocolStore.sendMessageWithReplyPredicate(deviceMessageSendEntity, deviceReplyMsgPredicate)
    }
    /**
     * 外设操作（以前叫：调料投放）
     * @param {String} deviceSn 设备SN号
     * @param {Array} seasoningBoxList 调料投放列表，每一个就是一个 seasoningItem 对象
     */
    manualAddSeasoning(deviceSn, seasoningBoxList) {
        if (!Array.isArray(seasoningBoxList)) {
            throw new TypeError('seasoningBoxList must be an array');
        }
        g_utils.writeLog("准备发送【外设操作】命令给设备：", deviceSn, seasoningBoxList)
        
        // 根据设备的真实的料盒列表信息进行封装
        let itemList = []
        for (let item of seasoningBoxList) {
            itemList.push(new SeasoningAddInfo(bytesToInt(hexStr2Bytes(item.driverId)), item.goal))
        }
    
        // for test
        // let item1 = new SeasoningAddInfo(0x0221, 10)
        // let item2 = new SeasoningAddInfo(0x0222, 50)
        let msgBody = new ManualAddSeasoningMsgBody(itemList)
        
        // 封装成发送消息
        let deviceMessageSendEntity = new DeviceMessageSend(deviceSn, MsgType.ManualAddSeasoning, msgBody)
        let deviceReplyMsgPredicate = (msg) => {
            // msg 是一个 DeviceMessageReceive 数据类型
            g_utils.writeLog("【外设操作】命令断言函数参数：", msg)
            // 设备接收后，回复结果 CommonConfirmReplyMsgBody
            let b = msg.msgBody.result > 0
            let status = msg.msgBody.status // 正确则回复收到的指令数；错误则回复对应错误原因
            if (b) {
                g_utils.writeLog("发送【外设操作】命令成功")
            } else {
                g_utils.writeLog("发送【外设操作】命令失败")
            }
            return true
        }
        return this.deviceProtocolStore.sendMessageWithReplyPredicate(deviceMessageSendEntity, deviceReplyMsgPredicate)
    }
    
    /**
     * 紧急处理
     * 若App有设置自动应急处理方式则自动下发对相关设备的操作方式，如下，并弹框或者语音提示；设备端进行应急处理，如降低功率、关闭火力等
     * @param {String} deviceSn 设备SN号
     * @param {String} targetId 外设地址
     * @param {number} goal 执行目标值
     */
    deviceEmergencyOperation(deviceSn, driverId, goal) {
        g_utils.writeLog("准备发送【紧急处理】命令给设备：", deviceSn)
        let msgBody = new DeviceEmergencyOperationMsgBody(bytesToInt(hexStr2Bytes(driverId)), goal)
        
        // 封装成发送消息
        let deviceMessageSendEntity = new DeviceMessageSend(deviceSn, MsgType.EmergencyOperation, msgBody)
        let deviceReplyMsgPredicate = (msg) => {
            // msg 是一个 DeviceMessageReceive 数据类型
            g_utils.writeLog("【紧急处理】命令断言函数参数：", msg)
            // 设备接收后，回复结果 CommonConfirmReplyMsgBody
            let b = msg.msgBody.result > 0
            let status = msg.msgBody.status
            if (b) {
                g_utils.writeLog("发送【紧急处理】命令成功")
            } else {
                g_utils.writeLog("发送【紧急处理】命令失败")
            }
            return true
        }
        return this.deviceProtocolStore.sendMessageWithReplyPredicate(deviceMessageSendEntity, deviceReplyMsgPredicate)
    }
    
}

export const deviceProtocolManualService = new DeviceProtocolManualService()